<?php
/**
 * Cache Class
 *
 * @package Extensions
 * @version @@VERSION@@
 * @subpackage Low-Cal_Vanilla
 * @copyright Damien Lebrun 2007
 * @author Damien Lebrun
 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GPLv2
 */


include_once('Class.File.php');

/**
 * Cache data in files
 * @package Extensions
 * @subpackage Low-Cal_Vanilla
 */

class LowCalVanilla_Cache {
	var $_Dir;
	var $_Ext;
	var $Context;

	function LowCalVanilla_Cache(&$Context) {
		$this->Context =& $Context;

		if (is_dir($Context->Configuration['LOWCALVANILLA_CACHE_DIR'])
		&&  is_writable($Context->Configuration['LOWCALVANILLA_CACHE_DIR'])
		) {
			$this->_Dir = $Context->Configuration['LOWCALVANILLA_CACHE_DIR'];
			$this->_Ext = $Context->Configuration['LOWCALVANILLA_CACHE_EXT'];
		}
	}

	function _SetHeader($Header) {
		return pack('CL', $Header['Serialized'], $Header['TTL']);
	}

	function _GetHeader($PackedHeader) {
		return unpack('C1Serialized/L1TTL', $PackedHeader);
	}

	function _Save(&$File, $Data, $TTL) {

		if ($TTL) {
			$TTL = time() + $TTL;
		}
		$Header = array(
			'Serialized' => 0,
			'TTL' => $TTL);

		if (!is_string($Data)) {
			$Data = serialize($Data);
			$Header['Serialized'] = 1;
		}

		if ($PackedHeader = $this->_SetHeader($Header)) {
			$return = $File->SetContent($PackedHeader . $Data);
		}
		$File->Clear();
		return $return;
	}

	function _GetFile($Key) {
		$Path = array($this->_Dir, md5($Key) . $this->_Ext);
		return new LowCalVanilla_File($this->Context, $Path);
	}

	function Add($Key, $Data, $TTL = 0) {
		$return = false;
		$File = $this->_GetFile($Key);
		$Header = '';
		if ($PackedHeader = $File->GetContent(5)) {
			$Header = $this->_GetHeader($PackedHeader);
		}

		// check the file exist(has an header, or it outdated
		if(!$Header
			|| (
				$Header['TTL']
				&& time() > $Header['TTL'])
		) {
			$return = $this->_Save($File, $Data, $TTL);
		}

		$File->Clear();
		return $return;
	}

	function ClearCache() {
		if ($handle = opendir($this->_Dir)) {
			while (false !== ($Item = readdir($handle))) {
				if ( !is_dir($this->_Dir . '/' . $Item)
					&& strrchr($Item, $this->_Ext)
				) {
					@unlink($this->_Dir . '/' . $Item);
				}
			}
			return true;
		} else {
			return false;
		}

	}

	function Delete($Key) {
		if ($File = $this->_GetFile($Key)) {
			return $File->Unlink();
		}
		return false;
	}

	function Fletch($Key) {
		$Header = null;
		$Content = '';
		$File = $this->_GetFile($Key);
		if ($PackedHeader = $File->GetContent(5, false)) {
			$Header = $this->_GetHeader($PackedHeader);
		}
		if ($Header
			&& (!$Header['TTL']
				|| ($Header['TTL']
					&& time() < $Header['TTL'])
			)
		) {
			$Content = $File->GetContent();
			if ($Header['Serialized']) {
				$Content = @unserialize($Content);
			}
		}
		$File->Clear();
		return $Content;
	}

	function GetLastModification($Key) {
		$File = $this->_GetFile($Key);
		return $File->GetLastModification();
	}

	function Store($Key, $Data, $TTL = 0) {
		$File = $this->_GetFile($Key);
		$return = $this->_Save($File, $Data, $TTL);
		$File->Clear();
		return $return;
	}
}